﻿using ApplicationBase.Core.Model;
using AutoMapper;
using IdentityService.Domain.Aggregates.UserAccountAggregate;
using IdentityService.Infrastructure;
using IdentityService.Infrastructure.Dtos;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;

namespace IdentityService.Application.QueryService
{
    public interface IUserAccountQueryService
    {
        Task<UserAccount> GetUserRoleAndClaimsByIdAsync(long id);
        Task<TableData<UserAccountDto>> GetListByKeyword(FindUserAccountByKeywordQueryRequest request);
        Task<UserAccountDto> GetDetailById(long id);
        Task<List<UserAccountDto>> FindByKeyword(string keyword);
    }

    public class UserAccountQueryService : IUserAccountQueryService
    {
        private readonly AppIdentityDbContext _dbContext;
        private readonly IMapper _mapper;
        public UserAccountQueryService(AppIdentityDbContext dbContext, IMapper mapper) 
            => (_dbContext, _mapper) = (dbContext, mapper);

        public async Task<UserAccount> GetUserRoleAndClaimsByIdAsync(long id)
        {
            return await _dbContext.UserAccount.AsNoTracking().FirstAsync(it => it.Id == id);
        }

        public async Task<TableData<UserAccountDto>> GetListByKeyword(FindUserAccountByKeywordQueryRequest request)
        {
            var query = _dbContext.UserAccount.AsNoTracking().Where(it => string.IsNullOrEmpty(request.KeyWords)
                || it.Id.ToString() == request.KeyWords || it.UserName.Contains(request.KeyWords)
                || (string.IsNullOrEmpty(it.PhoneNumber) && it.PhoneNumber!.Contains(request.KeyWords))
                || (string.IsNullOrEmpty(it.Email) && it.Email!.Contains(request.KeyWords)));

            var list = await query.Skip(request.PageInfo.GetStartIndex()).Take(request.PageInfo.Size).ToListAsync();
            var total = await query.CountAsync();

            return new TableData<UserAccountDto>
            {
                Data = _mapper.Map<List<UserAccountDto>>(list),
                TotalCount = total
            };
        }

        public async Task<UserAccountDto> GetDetailById(long id)
        {
            var user = await _dbContext.UserAccount.Include(it => it.UserInfo).Include(it => it.Roles)
                .FirstOrDefaultAsync(it => it.Id == id);
            return _mapper.Map<UserAccountDto>(user);
        }

        public async Task<List<UserAccountDto>> FindByKeyword(string keyword)
        {
            var list = await _dbContext.UserAccount.AsNoTracking()
                .Where(it => it.UserName.Contains(keyword) || it.Id.ToString().Contains(keyword)
                    || (string.IsNullOrEmpty(it.PhoneNumber) && it.PhoneNumber!.Contains(keyword))
                    || (string.IsNullOrEmpty(it.Email) && it.Email!.Contains(keyword)))
                .Take(10).ToListAsync();

            return _mapper.Map<List<UserAccountDto>>(list);
        }
    }

    public class FindUserAccountByKeywordQueryRequest
    {
        public string? KeyWords { get; set; }
        public PageInfo PageInfo { get; set; } = new();
    }
}
